/*
 * Copyright (c) 2024 endless-sky
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#pragma once

#include <gst/gst.h>
#define GST_USE_UNSTABLE_API
#include <gst/webrtc/webrtc.h>
#include <memory>
#include <map>
#include <mutex>
#include <thread>
#include <atomic>
#include <nlohmann/json.hpp>
#include "common_media_define.h"
#include "web_server.h"
#include "utils_time_cost.h"
#include "utils_noncopyable.h"
#include "utils_block_queue.h"
#include "record_playback.h"

namespace El {
namespace StreamService {

/**
 * @brief 回放状态枚举
 */
enum class PlaybackState {
    STOPPED,  ///< 停止状态
    PLAYING,  ///< 播放状态
    PAUSED    ///< 暂停状态
};

/**
 * @brief 回放媒体数据结构
 * 包含WebRTC回放客户端的媒体流相关数据
 */
struct PlaybackMediaData {
    GstElement *appsrcVideo;             ///< 视频应用源元素
    GstElement *appsrcAudio;             ///< 音频应用源元素
    El::Record::PlaybackPtr playback;    ///< 回放实例
};
using PlaybackMediaDataPtr = std::shared_ptr<PlaybackMediaData>;

/**
 * @brief 回放客户端连接结构
 * 包含单个WebRTC回放客户端连接的所有相关数据
 */
struct PlaybackClientConnection {
    void *wsConn;                       ///< WebSocket连接指针
    GstElement *pipeline;               ///< GStreamer管道元素
    GstElement *webrtcElement;          ///< WebRTC元素
    PlaybackMediaDataPtr mediaData;     ///< 媒体数据指针
    Utils::TimeCost timeCost;           ///< 时间消耗统计
    
    // 回放相关字段
    PlaybackState state{PlaybackState::STOPPED}; ///< 回放状态
    std::string currentFile;            ///< 当前播放文件名
    float playbackSpeed{1.0f};         ///< 播放速度
    uint32_t currentPosition{0};       ///< 当前播放位置(秒)

    /**
     * @brief 构造函数
     */
    PlaybackClientConnection() : wsConn(nullptr), pipeline(nullptr), webrtcElement(nullptr) {}
};

/**
 * @brief WebRTC录像回放服务器类
 * 提供基于GStreamer的WebRTC录像回放服务
 */
class StreamGstWebRTCPlayback {
    DISALLOW_COPY_AND_MOVE(StreamGstWebRTCPlayback);

public:
    /**
     * @brief 获取单例实例
     * @return StreamGstWebRTCPlayback& 单例实例引用
     */
    static StreamGstWebRTCPlayback &GetInstance();

    /**
     * @brief 启动WebRTC回放服务
     * @return bool 成功返回true，失败返回false
     */
    bool Start();

    /**
     * @brief 停止WebRTC回放服务
     */
    void Stop();

private:
    /**
     * @brief 私有构造函数（单例模式）
     */
    StreamGstWebRTCPlayback() = default;

    /**
     * @brief 析构函数
     */
    ~StreamGstWebRTCPlayback();

    /**
     * @brief 为客户端设置回放管道
     * @param clientConn 客户端连接对象
     * @param filename 回放文件名
     */
    bool SetupPlaybackPipeline(std::shared_ptr<PlaybackClientConnection> clientConn, const std::string &filename);

    /**
     * @brief 清理客户端连接
     * @param client 客户端连接对象
     */
    void CleanupClientConnection(std::shared_ptr<PlaybackClientConnection> client);

    /**
     * @brief 推送音视频帧到GStreamer
     * @param frame 媒体帧指针
     * @param mediaData 媒体数据对象
     */
    void PushFrame(const Media::MediaFramePtr &frame, PlaybackMediaDataPtr mediaData);

    /**
     * @brief 发送SDP到对端
     * @param desc WebRTC会话描述
     * @param client 客户端连接对象
     */
    void SendSdpToPeer(GstWebRTCSessionDescription *desc, std::shared_ptr<PlaybackClientConnection> client);

    /**
     * @brief 发送ICE候选到对端
     * @param mlineindex 媒体行索引
     * @param candidate ICE候选字符串
     * @param client 客户端连接对象
     */
    void SendIceCandidateToPeer(guint mlineindex, gchar *candidate, std::shared_ptr<PlaybackClientConnection> client);

    /**
     * @brief Offer创建完成回调
     * @param promise GStreamer Promise对象
     * @param webrtc WebRTC元素
     * @param client 客户端连接对象
     */
    void OnOfferCreated(GstPromise *promise, GstElement *webrtc, PlaybackClientConnection *client);

    /**
     * @brief 协商需要回调
     * @param webrtc WebRTC元素
     * @param client 客户端连接对象
     */
    void OnNegotiationNeeded(GstElement *webrtc, PlaybackClientConnection *client);

    /**
     * @brief ICE候选回调
     * @param webrtc WebRTC元素（未使用）
     * @param mlineindex 媒体行索引
     * @param candidate ICE候选字符串
     * @param client 客户端连接对象
     */
    void OnIceCandidate([[maybe_unused]] GstElement *webrtc,
                        guint mlineindex,
                        gchar *candidate,
                        PlaybackClientConnection *client);

    /**
     * @brief 处理WebSocket事件
     * @param event WebSocket事件对象
     */
    void HandleWebSocketEvent(std::shared_ptr<El::WebServer::WebSocketEvent> &event);

    /**
     * @brief 处理WebSocket事件的主循环
     */
    void ProcessWebSocketEvents();

    /**
     * @brief 处理WebSocket消息
     * @param client 客户端连接对象
     * @param message 消息内容
     */
    void HandleWebSocketMessage(std::shared_ptr<PlaybackClientConnection> client, const std::string &message);

    /**
     * @brief 发送WebSocket文本消息
     * @param connection WebSocket连接指针
     * @param message 消息内容
     */
    void SendWebSocketTextMessage(void *connection, const std::string &message);

    /**
     * @brief 处理WebRTC Answer
     * @param client 客户端连接对象
     * @param params RPC参数
     * @param id RPC请求ID
     */
    void HandleWebRTCAnswer(std::shared_ptr<PlaybackClientConnection> client,
                            const nlohmann::json &params,
                            const nlohmann::json &id);

    /**
     * @brief 处理WebRTC ICE候选（请求模式）
     * @param client 客户端连接对象
     * @param params RPC参数
     * @param id RPC请求ID
     */
    void HandleWebRTCIceCandidate(std::shared_ptr<PlaybackClientConnection> client,
                                  const nlohmann::json &params,
                                  const nlohmann::json &id);

    /**
     * @brief 处理WebRTC ICE候选（通知模式）
     * @param client 客户端连接对象
     * @param params RPC参数
     */
    void HandleWebRTCIceCandidateNotification(std::shared_ptr<PlaybackClientConnection> client, const nlohmann::json &params);

    /**
     * @brief 处理WebRTC Ready信号
     * @param client 客户端连接对象
     * @param params RPC参数
     * @param id RPC请求ID
     */
    void HandleWebRTCReady(std::shared_ptr<PlaybackClientConnection> client,
                           const nlohmann::json &params,
                           const nlohmann::json &id);

    /**
     * @brief 处理回放开始请求
     * @param client 客户端连接对象
     * @param params RPC参数
     * @param id RPC请求ID
     */
    void HandlePlaybackStart(std::shared_ptr<PlaybackClientConnection> client,
                            const nlohmann::json &params,
                            const nlohmann::json &id);

    /**
     * @brief 处理回放停止请求
     * @param client 客户端连接对象
     * @param params RPC参数
     * @param id RPC请求ID
     */
    void HandlePlaybackStop(std::shared_ptr<PlaybackClientConnection> client,
                           const nlohmann::json &params,
                           const nlohmann::json &id);

    /**
     * @brief 处理回放暂停请求
     * @param client 客户端连接对象
     * @param params RPC参数
     * @param id RPC请求ID
     */
    void HandlePlaybackPause(std::shared_ptr<PlaybackClientConnection> client,
                            const nlohmann::json &params,
                            const nlohmann::json &id);

    /**
     * @brief 处理回放恢复请求
     * @param client 客户端连接对象
     * @param params RPC参数
     * @param id RPC请求ID
     */
    void HandlePlaybackResume(std::shared_ptr<PlaybackClientConnection> client,
                             const nlohmann::json &params,
                             const nlohmann::json &id);

    /**
     * @brief 处理回放定位请求
     * @param client 客户端连接对象
     * @param params RPC参数
     * @param id RPC请求ID
     */
    void HandlePlaybackSeek(std::shared_ptr<PlaybackClientConnection> client,
                           const nlohmann::json &params,
                           const nlohmann::json &id);

    /**
     * @brief 处理回放变速请求
     * @param client 客户端连接对象
     * @param params RPC参数
     * @param id RPC请求ID
     */
    void HandlePlaybackSetSpeed(std::shared_ptr<PlaybackClientConnection> client,
                               const nlohmann::json &params,
                               const nlohmann::json &id);

    /**
     * @brief 发送RPC响应
     * @param client 客户端连接对象
     * @param id 请求ID
     * @param result 响应结果
     */
    void SendRpcResponse(std::shared_ptr<PlaybackClientConnection> client,
                         const nlohmann::json &id,
                         const nlohmann::json &result);

    /**
     * @brief 发送RPC错误响应
     * @param client 客户端连接对象
     * @param id 请求ID
     * @param code 错误码
     * @param message 错误消息
     * @param data 错误数据（可选）
     */
    void SendRpcError(std::shared_ptr<PlaybackClientConnection> client,
                      const nlohmann::json &id,
                      int code,
                      const std::string &message,
                      const nlohmann::json &data);

    /**
     * @brief 发送RPC通知
     * @param client 客户端连接对象
     * @param method 方法名
     * @param params 参数
     */
    void SendRpcNotification(std::shared_ptr<PlaybackClientConnection> client,
                             const std::string &method,
                             const nlohmann::json &params);

    /**
     * @brief 获取AAC采样率索引
     * @param sampleRate 采样率
     * @return uint8_t 采样率索引
     */
    uint8_t GetAacSampleRateIndex(int sampleRate);

private:
    /// 事件队列，用于处理WebSocket事件
    std::unique_ptr<El::Utils::BlockingQueue<std::shared_ptr<El::WebServer::WebSocketEvent>>> eventQueue_;
    std::unique_ptr<std::thread> processThread_;                         ///< 事件处理线程
    std::atomic<bool> running_{false};                                   ///< 运行状态标志
    bool audioEnable_{false};                                            ///< 音频启用标志
    std::map<void *, std::shared_ptr<PlaybackClientConnection>> connections_; ///< 客户端连接映射表
    std::mutex connectionsMutex_;                                        ///< 连接互斥锁
    std::string audioCodec_;                                             ///< 音频编解码器类型
    int audioSampleRate_{8000};                                          ///< 音频采样率
};

} // namespace StreamService
} // namespace El